package com.example.fileupload.service.impl;

import com.example.fileupload.entity.FileInfo;
import com.example.fileupload.service.FileService;
import com.example.fileupload.mapper.FileInfoMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.UUID;
import java.time.LocalDateTime;

@Service
public class FileServiceImpl implements FileService {
    
    private static final Logger logger = LoggerFactory.getLogger(FileServiceImpl.class);
    
    @Autowired
    private FileInfoMapper fileInfoMapper;
    
    private final String STORAGE_DIR = "C:\\media_files\\";
    
    public FileServiceImpl() {
        // 确保存储目录存在
        File dir = new File(STORAGE_DIR);
        if (!dir.exists()) {
            logger.info("存储目录不存在，创建中: {}", STORAGE_DIR);
            boolean created = dir.mkdirs();
            if (created) {
                logger.info("存储目录创建成功: {}", STORAGE_DIR);
            } else {
                logger.error("存储目录创建失败: {}", STORAGE_DIR);
            }
        } else {
            logger.info("存储目录已存在: {}", STORAGE_DIR);
        }
        
        // 检查目录权限
        if (dir.canWrite()) {
            logger.info("存储目录有写入权限: {}", STORAGE_DIR);
        } else {
            logger.error("存储目录没有写入权限: {}", STORAGE_DIR);
        }
    }
    
    @Override
    public FileInfo saveFile(MultipartFile file) throws IOException {
        logger.info("开始保存文件，原始文件名: {}", file.getOriginalFilename());
        
        String originalFilename = file.getOriginalFilename();
        String contentType = file.getContentType();
        long fileSize = file.getSize();
        
        logger.info("文件信息 - 类型: {}, 大小: {} 字节", contentType, fileSize);
        
        // 生成唯一文件名
        String fileName = UUID.randomUUID().toString() + "-" + originalFilename;
        String filePath = STORAGE_DIR + fileName;
        
        logger.info("将保存到路径: {}", filePath);
        
        try {
            // 保存文件到磁盘
            Path path = Paths.get(filePath);
            Files.write(path, file.getBytes());
            logger.info("文件成功写入磁盘");
            
            // 验证文件是否存在
            File savedFile = new File(filePath);
            if (savedFile.exists() && savedFile.length() == fileSize) {
                logger.info("文件验证成功，大小匹配");
            } else {
                logger.warn("文件验证警告: 文件大小不匹配或文件不存在");
            }
        } catch (IOException e) {
            logger.error("文件写入磁盘失败: {}", e.getMessage(), e);
            throw e;
        }
        
        // 创建文件信息对象
        FileInfo fileInfo = new FileInfo();
        fileInfo.setOriginalName(originalFilename);
        fileInfo.setFileName(fileName);
        fileInfo.setFilePath(filePath);
        fileInfo.setFileSize(fileSize);
        fileInfo.setUploadTime(LocalDateTime.now());
        fileInfo.setContentType(contentType);
        
        try {
            // 存储到数据库
            fileInfoMapper.insert(fileInfo);
            logger.info("文件信息成功存储到数据库，文件ID: {}", fileInfo.getId());
        } catch (Exception e) {
            logger.error("文件信息存储到数据库失败: {}", e.getMessage(), e);
            // 如果数据库存储失败，尝试删除已保存的文件
            try {
                File tempFile = new File(filePath);
                if (tempFile.exists()) {
                    tempFile.delete();
                    logger.info("数据库存储失败，已删除临时文件");
                }
            } catch (Exception deleteEx) {
                logger.error("删除临时文件失败: {}", deleteEx.getMessage());
            }
            throw e;
        }
        
        return fileInfo;
    }
    
    @Override
    public List<FileInfo> getAllFiles() {
        return fileInfoMapper.selectList(null);
    }
    
    @Override
    public FileInfo getFileById(Long id) {
        logger.info("根据ID获取文件信息: {}", id);
        
        try {
            FileInfo fileInfo = fileInfoMapper.selectById(id);
            
            if (fileInfo != null) {
                logger.info("找到文件信息，文件名: {}, 文件路径: {}", 
                        fileInfo.getOriginalName(), fileInfo.getFilePath());
                
                // 验证文件是否存在于磁盘
                File file = new File(fileInfo.getFilePath());
                if (file.exists()) {
                    logger.info("文件存在于磁盘，大小: {} 字节", file.length());
                } else {
                    logger.error("文件不存在于磁盘: {}", fileInfo.getFilePath());
                }
            } else {
                logger.warn("未找到文件ID: {}", id);
            }
            
            return fileInfo;
        } catch (Exception e) {
            logger.error("获取文件信息失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public boolean deleteFile(Long id) {
        FileInfo fileInfo = fileInfoMapper.selectById(id);
        if (fileInfo != null) {
            try {
                // 删除物理文件
                File file = new File(fileInfo.getFilePath());
                // 先从数据库删除
                int result = fileInfoMapper.deleteById(id);
                // 然后删除文件
                if (result > 0) {
                    file.delete();
                    return true;
                }
                return false;
            } catch (Exception e) {
                // 异常情况下也尝试从数据库删除
                fileInfoMapper.deleteById(id);
                return true;
            }
        }
        return false;
    }
}